package parte1;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Scanner;

public class Agenda {
	private static Usuario usuario;
	private static Scanner teclado;
	private static boolean executando;
	private static final String[] FORMAS_DE_CONTATO = { "Telefone", "Email",
			"Outro" };
	private static final String MENU_PRINCIPAL = "Menu:\n  1 - Perfil\n  2 - Contatos\n  3 - Eventos\n  0 - Sair\n";
	private static final String MENU_CONTATOS = "1 - Selecionar Contato\n2 - Adicionar Contato\n3 - Remover Contato\n0 - Sair";
	private static final String MENU_EVENTOS = "1 - Selecionar Evento\n2 - Visualizar eventos passados\n3 - Visualizar eventos futuros\n4 - Adicionar Evento\n5 - Remover Evento\n0 - Sair";
	private static final String MENU_PERFIL = "1 - Editar perfil\n2 - Gerenciar Contatos\n3 - Gerenciar Eventos\n0 - Sair";
	private static final String MENU_ALTERA_DADOS = "O que você deseja alterar?\n1 - Nome\n2 - Descrição\n3 - E-mail";

	public static void main(String[] args) {
		teclado = new Scanner(System.in);
		System.out.println("--AGENDA--");
		inicializacao();
		while (executando) {
			try {
				menuPrincipal();
			} catch (Exception e) {
				System.out.println("Um erro foi encontrado");
			}
		}
	}

	private static void inicializacao() {
		executando = true;
		try {
			FileInputStream fi = new FileInputStream("Usuario.dat");
			ObjectInputStream oi = new ObjectInputStream(fi);
			usuario = (Usuario) oi.readObject();
			oi.close();
		} catch (Exception e) {
			while (true)
				if (criarPerfil() == true)
					break;
		}
		System.out.println("Olá, " + usuario.getNome() + "!");
	}

	private static boolean criarPerfil() {
		System.out.println("Digite seu nome:");
		String nome = teclado.nextLine();
		System.out.println("Digite uma descrição:");
		String descricao = teclado.nextLine();
		System.out.println("Digite seu email:");
		String email = teclado.nextLine();

		try {
			usuario = new Usuario(nome, descricao, email);
		} catch (Exception e) {
			System.out.println("Por favor, tente novamente");
			return false;
		}
		return true;
	}

	private static void menuPrincipal() {
		System.out.println(MENU_PRINCIPAL);
		String opcao;
		int operacao = -1;

		opcao = teclado.nextLine();
		try {
			operacao = Integer.parseInt(opcao);
		} catch (Exception e) {
			operacao = -1;
		}
		switch (operacao) {
		case 1:
			menuPerfil();
			break;
		case 2:
			menuContatos();
			break;
		case 3:
			menuEventos();
			break;
		case 0:
			finalizacao();
			executando = false;
			break;
		default:
			System.out.println("Opção inválida\n");
			break;
		}
	}

	private static void menuPerfil() {
		System.out.println(usuario.toString());
		System.out.println(MENU_PERFIL);
		String opcao;
		int operacao = -1;

		opcao = teclado.nextLine();
		try {
			operacao = Integer.parseInt(opcao);
		} catch (Exception e) {
			operacao = -1;
		}
		switch (operacao) {
		case 1:
			menuAlteraDados();
			break;
		case 2:
			menuContatos();
			break;
		case 3:
			menuEventos();
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida\n");
			break;
		}
	}

	private static void menuAlteraDados() {
		System.out.println(MENU_ALTERA_DADOS);
		String opcao;
		int operacao = -1;

		opcao = teclado.nextLine();
		try {
			operacao = Integer.parseInt(opcao);
		} catch (Exception e) {
			operacao = -1;
		}
		switch (operacao) {
		case 1:
			System.out.println("Digite um novo nome: ");
			usuario.setNome(teclado.nextLine());
			break;
		case 2:
			System.out.println("Digite uma nova descrição: ");
			usuario.setDescricao(teclado.nextLine());
			break;
		case 3:
			System.out.println("Digite um novo e-mail: ");
			usuario.setEmail(teclado.nextLine());
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida\n");
			break;
		}
	}

	private static void menuEventos() {
		System.out.println(MENU_EVENTOS);
		String opcao;
		int operacao = -1;

		opcao = teclado.nextLine();
		try {
			operacao = Integer.parseInt(opcao);
		} catch (Exception e) {
			operacao = -1;
		}
		switch (operacao) {
		case 1:
			Evento e = buscarEvento();
			if (e.equals(null)) {
				System.out.println("Evento não existe");
				menuContatos();
			}
			usarEvento(e);
			break;
		case 2:
			for (Evento eventoPassado : usuario.getEventosPassados()) {
				System.out.println(eventoPassado);
			}
			menuEventos();
			break;
		case 3:
			for (Evento eventoFuturo : usuario.getEventosFuturos()) {
				System.out.println(eventoFuturo);
			}
			menuEventos();
			break;
		case 4:
			cadastrarEvento();
			break;
		case 5:
			Evento evento = buscarEvento();
			if (!evento.equals(null))
				usuario.removeEvento(evento);
			menuEventos();
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida\n");
			break;
		}
	}

	private static void menuContatos() {
		for (Contato contato : usuario.getContatos()) {
			System.out.println(contato.getNome());
		}
		System.out.println(MENU_CONTATOS);
		String opcao;
		int operacao = -1;

		opcao = teclado.nextLine();
		try {
			operacao = Integer.parseInt(opcao);
		} catch (Exception e) {
			operacao = -1;
		}
		switch (operacao) {
		case 1:
			Contato c = buscarContato();
			if (c.equals(null)) {
				System.out.println("Contato não existe");
				menuContatos();
			}
			usarContato(c);
			break;
		case 2:
			cadastrarContato();
			break;
		case 3:
			Contato resultado = buscarContato();
			if (!resultado.equals(null))
				usuario.removeContato(resultado);
			menuContatos();
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida\n");
			break;
		}
	}

	private static void finalizacao() {
		try {
			FileOutputStream fo = new FileOutputStream("Usuario.dat");
			ObjectOutputStream oo = new ObjectOutputStream(fo);
			oo.writeObject(usuario);
			oo.close();
		} catch (Exception e) {
			finalizacao();
		}
	}

	private static void cadastrarContato() {
		System.out.println("Digite o nome do contato:");

		String nome = teclado.nextLine();
		if (!Verificador.nomeValido(nome)) {
			System.out.println("Nome invalido");
		} else {
			System.out.println("Digite o endereço do contato:");
			String endereco = teclado.nextLine();

			System.out
					.println("Digite o aniversário do contato (formato: dd/mm):");
			String aniversario = teclado.nextLine();
			String[] diaMes = aniversario.split("/");

			Contato c = new Contato(nome, endereco,
					Integer.parseInt(diaMes[0]), Integer.parseInt(diaMes[1]));
			cadastrarFormadeContato(c);
			usuario.addContato(c);
		}
	}

	private static void cadastrarFormadeContato(Contato c) {
		System.out.println("Escolha uma forma de contato:");
		int formaEscolhida = 0;
		for (int i = 1; i <= FORMAS_DE_CONTATO.length; i++) {
			System.out.println(i + " - " + FORMAS_DE_CONTATO[i - 1]);
		}
		try {
			formaEscolhida = Integer.parseInt(teclado.nextLine());
		} catch (Exception e) {
			formaEscolhida = -1;
		}

		FormaDeContato f = null;

		switch (formaEscolhida) {
		case 1:
			System.out.println("Digite o número de Telefone:");
			f = new Telefone(teclado.nextLine());
			c.addFormaDeContato(f);
			break;

		case 2:
			System.out.println("Digite o endereço de Email:");
			f = new Email(teclado.nextLine());
			c.addFormaDeContato(f);
			break;
		case 3:
			System.out
					.println("Digite o tipo da forma de contato que você vai adicionar: ");
			String tipo = teclado.nextLine();
			System.out.println("Digite o endereço da forma de contato: ");
			String endereco = teclado.nextLine();
			System.out.println("Digite um comentário da forma de contato: ");
			String comentario = teclado.nextLine();
			f = new FormaDeContato(tipo, endereco, comentario);
			c.addFormaDeContato(f);
			break;
		default:
			System.out.println("Opção inválida");
			break;
		}

	}

	private static void cadastrarEvento() {
		System.out.println("Digite o nome do evento:");
		String nome = teclado.nextLine();

		System.out.println("Digite a data do evento (formato: dd/mm/AAAA):");
		String data = teclado.nextLine();
		String[] dataSeparada = data.split("/");

		System.out.println("Digite o horário do evento (formato: HH:mm):");
		String horario = teclado.nextLine();
		String[] horaSeparada = horario.split(":");

		System.out.println("Digite a duração do evento (formato: HH:MM) :");
		String duracao = teclado.nextLine();

		System.out.println("Digite uma descrição do evento:");
		String descricao = teclado.nextLine();

		System.out
				.println("Digite um tipo para o evento (exemplo: encontro, prova):");
		String tipo = teclado.nextLine();

		Evento e1 = new Evento(nome, Integer.parseInt(dataSeparada[0]),
				Integer.parseInt(dataSeparada[1]),
				Integer.parseInt(dataSeparada[2]),
				Integer.parseInt(horaSeparada[0]),
				Integer.parseInt(horaSeparada[1]), duracao + ":00", descricao,
				tipo);

		try {
			usuario.addEvento(e1);
		} catch (Exception e) {
			System.out.println(e.getMessage());
			menuEventos();
		}
	}

	private static Contato buscarContato() {
		System.out.println("Digite o nome ou uma parte inicial do nome:");
		String buscaNome = teclado.nextLine();
		ArrayList<Contato> possiveisContatos = new ArrayList<Contato>();

		for (Contato c : usuario.getContatos())
			if (c.getNome().toLowerCase().startsWith(buscaNome.toLowerCase()))
				possiveisContatos.add(c);

		if (possiveisContatos.isEmpty())
			return null;
		else {
			int opcao = 0;
			Contato resultado = null;
			System.out.println("Escolha um dos contatos:\n");
			for (int i = 0; i < possiveisContatos.size(); i++)
				System.out.println((i + 1) + " - "
						+ possiveisContatos.get(i).getNome());
			try {
				opcao = Integer.parseInt(teclado.nextLine());
				resultado = possiveisContatos.get(opcao - 1);
			} catch (Exception e) {
				System.out.println("Opção inválida");
			}
			return resultado;
		}
	}

	private static Evento buscarEvento() {
		System.out
				.println("Digite o nome do evento ou uma parte inicial do mesmo:");
		String buscaEvento = teclado.nextLine();
		ArrayList<Evento> possiveisEventos = new ArrayList<Evento>();

		for (Evento e : usuario.getEventos())
			if (e.getNome().toLowerCase().startsWith(buscaEvento.toLowerCase()))
				possiveisEventos.add(e);

		if (possiveisEventos.isEmpty())
			return null;
		else if (possiveisEventos.size() == 1)
			return possiveisEventos.get(0);
		else {
			int opcao = 0;
			Evento resultado = null;
			System.out.println("Escolha um dos eventos:\n");
			for (int i = 0; i < possiveisEventos.size(); i++)
				System.out.println((i + 1) + possiveisEventos.get(i).getNome());
			try {
				opcao = Integer.parseInt(teclado.nextLine());
				resultado = possiveisEventos.get(opcao - 1);
			} catch (Exception e) {
				System.out.println("Opção inválida");
			}
			return resultado;
		}
	}

	private static void usarContato(Contato c) {
		System.out.println(c.toString() + "\n\n Digite o que deseja fazer:\n"
				+ "  1 - Ver as formas de contato\n"
				+ "  2 - Ver os eventos em que este contato participa\n"
				+ "  3 - Adicionar uma forma de contato\n"
				+ "  4 - Adicionar a um evento\n" + "  0 - Sair");
		String opcao = teclado.nextLine();
		int op = 0;
		try {
			op = Integer.parseInt(opcao);
		} catch (Exception e) {
			op = -1;
		}

		switch (op) {
		case 1:
			for (FormaDeContato f : c.getFormasDeContato()) {
				System.out.println(f.getEndereco());
			}
			break;
		case 2:
			if (c.getEventos().size() == 0) {
				System.out.println("Não há eventos no contato");
				break;
			}
			for (Evento e : c.getEventos()) {
				System.out.println(e.getNome() + "\n");
			}
			break;
		case 3:
			cadastrarFormadeContato(c);
			break;
		case 4:
			int escolha = 0;
			Evento resultado = null;
			System.out.println("Escolha um dos eventos:\n");
			for (int i = 0; i < usuario.getEventos().size(); i++)
				System.out.println((i + 1) + " - "
						+ usuario.getEventos().get(i).getNome());

			try {
				escolha = Integer.parseInt(teclado.nextLine());
				resultado = usuario.getEventos().get(escolha - 1);
			} catch (Exception e) {
				System.out.println("Opção inválida");
			}
			c.addEvento(resultado);
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida");
			break;
		}
		menuContatos();
	}

	private static void usarEvento(Evento e) {
		System.out.println(e.toString()
				+ "\n\n  1 - Ver os contatos no evento\n" + "  0 - Sair");
		String opcao = teclado.nextLine();
		int op = 0;
		try {
			op = Integer.parseInt(opcao);
		} catch (Exception exc) {
			op = -1;
		}

		switch (op) {
		case 1:
			if (e.getContatosNoEvento().size() == 0) {
				System.out.println("Não há contatos no evento\n");
				break;
			}
			for (Contato contato : e.getContatosNoEvento()) {
				System.out.println(contato);
				menuContatoEmEvento(e);
			}
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida");
			break;
		}
	}

	private static void menuContatoEmEvento(Evento e) {
		System.out
				.println("\n   1 - Adicionar Contatos ao Evento\n   2 - Remover Contatos do Evento\n   0 - Sair");
		String opcao = teclado.nextLine();
		int op = 0;
		try {
			op = Integer.parseInt(opcao);
		} catch (Exception exc) {
			op = -1;
		}

		switch (op) {
		case 1:
			Contato contato = buscarContato();
			if (contato.equals(null)) {
				System.out.println("Contato inexistente");
				usarEvento(e);
			}
			e.addContato(contato);
			contato.addEvento(e);
			break;
		case 2:
			Contato c = buscarContato();
			if (c.equals(null)) {
				System.out.println("Contato inexistente");
				usarEvento(e);
			}
			e.removeContato(c);
			break;
		case 0:
			break;
		default:
			System.out.println("Opção inválida");
			break;
		}
	}

}
